package tencent_game_server;

import java.io.Serializable;
import java.net.MalformedURLException;
import java.rmi.AlreadyBoundException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.HashMap;
import java.util.HashSet;
import java.util.concurrent.TimeUnit;

import javax.management.openmbean.OpenDataException;

import org.json.JSONObject;

import util.JsonUtil;

public class GameServer implements IGameServer,Serializable{
	/**
	 * 
	 */
	private static final long serialVersionUID = -6046318431602911688L;
	IServer server=null;
	public GameServer() throws MalformedURLException, RemoteException, NotBoundException {
		// TODO Auto-generated constructor stub
		System.out.println("one game Server");
		server=(IServer) Naming.lookup("rmi://localhost:8888/server");
	}
	enum Status{
		offline,
		idle,
		inroom
	}
	static HashMap<String, Integer> score=new HashMap<>();
	HashMap<String, Status> userList=new HashMap<>();
	
	HashMap<String, String> userRoom=new HashMap<>();
	HashMap<String, GameRoom> roomHash=new HashMap<>();
	
	private int getScore(String uName){
		synchronized (score) {
			Integer integer=score.get(uName);
			if(integer==null){
				score.put(uName, 0);
				return 0;
			}
			return integer;
		}

	}
	public static void changeScore(String uName,int value){
		synchronized (score) {
			Integer integer=score.get(uName);
			if(integer==null){
				integer=0;
			}
			score.put(uName,integer+value);
		}
		
	}
	public static void main(String[] args) {
		
		try {
			GameServer gServer=new GameServer();
			Registry reg;

//        	LocateRegistry.createRegistry(8888);
			Naming.bind("rmi://localhost:8888/gameserver",gServer);
			System.out.println("GameServer");
			while (true) {
				Thread.sleep(5000);
				
			}
			
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (RemoteException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (AlreadyBoundException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (NotBoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("GameServer stop");
		
	}
	private JSONObject open(String userName,String room){
		if(room.isEmpty())
			return JsonUtil.msgJson("room name can`t be empty"); 
		synchronized (userList){
			Status status=userList.get(userName);
			if(status!=Status.idle){
				return JsonUtil.msgJson("open failed you are ["+status+"]"); 
			}
		}
		synchronized (userRoom) {
			GameRoom gRoom=null;
			try {
				gRoom=roomHash.get(room);
				if(gRoom!=null)
					return JsonUtil.msgJson("room is existed");
				gRoom = new GameRoom(userName,room,server);
				gRoom.start();
				userRoom.put(userName, room);
				roomHash.put(room,gRoom);
				
				synchronized (userList){
					userList.put(userName, Status.inroom);
				}
				
				return JsonUtil.msgJson("open success"); 
			} catch (MalformedURLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (RemoteException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (NotBoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			return JsonUtil.msgJson("open falied"); 
		}
	}
	private JSONObject join(String userName,String room){
		synchronized (userList){
			Status status=userList.get(userName);
			if(status!=Status.idle){
				return JsonUtil.msgJson("join failed you are ["+status+"]"); 
			}
		}
		synchronized (userRoom) {
			String nowRoom=null;
			nowRoom=userRoom.get(userName);
			if(nowRoom!=null)
				return JsonUtil.msgJson("you are in the room ["+nowRoom+"] , if you want to join new room , quit please");
			GameRoom gRoom=null;
			gRoom=roomHash.get(room);
			if(gRoom==null)
				return JsonUtil.msgJson("battle room is not exist");
			gRoom.addUser(userName);
			userRoom.put(userName, room);
			synchronized (userList){
				userList.put(userName, Status.inroom);
			}
			return JsonUtil.msgJson("join success");
		}
	}
	private JSONObject quit(String userName,String room){
		synchronized (userList){
			Status status=userList.get(userName);
			if(status!=Status.inroom){
				return JsonUtil.msgJson("quit failed you are ["+status+"]"); 
			}
		}
		synchronized (userRoom) {
			String nowRoom=null;
			nowRoom=userRoom.get(userName);
			if(nowRoom==null)
				return JsonUtil.msgJson("you are not in a room");
			GameRoom gRoom=null;
			gRoom=roomHash.get(nowRoom);
			if(gRoom==null)
				return JsonUtil.msgJson("you are not in a room");
			gRoom.quite(userName);
			userRoom.remove(userName);
			if(gRoom.userNum()==0)
				roomHash.remove(nowRoom);
			synchronized (userList){
				userList.put(userName, Status.idle);
			}
			return JsonUtil.msgJson("quit success");
		}
	}
	private JSONObject cast(String userName,String request){
		synchronized (userList){
			Status status=userList.get(userName);
			if(status!=Status.inroom){
				return JsonUtil.msgJson("you are not in room"); 
			}
		}
		synchronized (userRoom) {
			String room=userRoom.get(userName);
			if(room==null)
				return JsonUtil.msgJson("can`t find room name");
			GameRoom gRoom=roomHash.get(room);
			if(gRoom==null)
				return JsonUtil.msgJson("room not exist");
			boolean flag=gRoom.request(userName, request);
			if(flag)
				return JsonUtil.msgJson("cast success ,your cast "+request); 
			else
				return JsonUtil.msgJson("cast failed ,you have casted in the room ,please waiting for result");
		}
	}
	private JSONObject info(String userName,String request){
		synchronized (userList){
			if("all".equals(request)){
				StringBuffer sb=new StringBuffer();
				sb.append("your name is [").append(userName).append("]\n");
				for(String s:userList.keySet()){
					Status status=userList.get(s);
					if(status==Status.offline)
						continue;
					sb.append("username : [").append(s).append("],");
					if(status==Status.inroom)
						sb.append("status : [").append(status.toString()).append(":").append(userRoom.get(s)).append("],");
					else
						sb.append("status : [").append(status.toString()).append("],");
					sb.append("score : [").append(getScore(s)).append("]\n");
				}
				return JsonUtil.msgJson(sb.toString());
			}else{
				StringBuffer sb=new StringBuffer();
				sb.append("username : [").append(request).append("],");
				sb.append("status : [").append(userList.get(request)).append("],");
				sb.append("score : [").append(getScore(request)).append("]\n");
				return JsonUtil.msgJson(sb.toString());
			}
			
		}
	}
	private JSONObject login(String userName,String request){
		synchronized (userList) {
			Status sta=userList.get(userName);
			if(sta==null||sta==Status.offline){
				userList.put(userName, Status.idle);
				return JsonUtil.msgJson("login success");
			}else
				return JsonUtil.msgJson("login faild user is online");
			
		}
		
	}
	private JSONObject logout(String userName,String request){
		synchronized (userList) {
			Status sta=userList.get(userName);
			if(sta==null||sta==Status.offline){
				return JsonUtil.msgJson("logout failed user is offline");
			}else{
				userList.replace(userName, Status.offline);
				return JsonUtil.msgJson("logout success");
			}
			
		}
	}
	@Override
	public JSONObject handle(String userName, JSONObject request) throws RemoteException {
		// TODO Auto-generated method stub
		String op=request.getString("op");
		switch (op) {
			case "open":return open(userName,request.getString("data"));
			case "join":return join(userName,request.getString("data"));
			case "cast":return cast(userName,request.getString("data"));
			case "info":return info(userName,request.getString("data"));
			case "login":return login(userName,request.getString("data"));
			case "logout":return logout(userName,request.getString("data"));
			case "quit":return quit(userName,request.getString("data"));
			default :return JsonUtil.msgJson("operation is not correct : ["+op+"]");
		}
		//return null;
	}
}
